﻿using System; 
using System.Linq;
using System.Text;
using System.Collections.Generic;

namespace System.Erp.Runtime.Services
{
    /// <summary>
    /// 服务提供者的基础实现，他实现了服务的获取，如果未获得将转发给父对象（如果有的话）
    /// </summary>
    public abstract class CompositionServiceProviderBase : ICompositionServiceProvider
    {
        /// <summary>
        /// 创建 CompositionServiceProviderBase 实例，派生类才能调用。
        /// </summary>
        protected CompositionServiceProviderBase():this(null) { }

        /// <summary>
        /// 创建 CompositionServiceProviderBase 实例并传入父对象。派生类才能使用。
        /// </summary>
        /// <param name="parent">提供链式操作的父对象。当当前服务提供者未能找到实现时，将转发请求到父对象。</param>
        protected CompositionServiceProviderBase(ICompositionServiceProvider parent)
        {
            _parentProvider = parent;
        }

        /// <summary>
        /// 根据当前请求获取对象的创建者对象
        /// </summary>
        /// <param name="serviceKey">服务请求对象描述</param>
        /// <param name="creator">如果对象的实现，将返回他，否则返回null</param>
        /// <returns>是否成功找到创建者对象</returns>
        protected abstract  bool TryGetCreator(CompositionServiceKey serviceKey,out  ICreator creator);

        /// <summary>
        /// 获取指定typeKey的服务接口实现
        /// </summary>
        /// <param name="key">要获得服务接口类型和对象键</param>
        /// <returns>如果找到此服务将返回服务的实例，否则返回null</returns>
        public object GetService(CompositionServiceKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            ICreator creator;
            if (this.TryGetCreator(key, out creator))
            {
                return creator.GetInstance(this, key);
            }
            if (this._parentProvider != null)
            {
                return this._parentProvider.GetService(key);
            }
            return null;
        }

        private readonly ICompositionServiceProvider _parentProvider;
        /// <summary>
        /// 返回容器的父处理器。
        /// </summary>
        public ICompositionServiceProvider Parent
        {
            get { return _parentProvider; }
        }

    }
}